import pandas as pd
import os
import re
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Alignment
'''
出来肖淋方得发货表数据
1.根据发货表模板创建按商品名称分类的发货表
2.再订单表中查询对应商品的订单信息 维度：（商品名称，店长id）
3.和计调的统计表对比商品数量是否一致
4.计算填充的发货数量，需要计算，公式=规格*数量
'''
#配置发货表模板
delivery_template_path = r'C.PA直播间-新商城发货表_模板.xlsx'
#配置订单表
order_table_path = r'e:\vx\xwechat_files\wxid_xwi9k2ekef8422_e5fc\msg\file\2025-10\2025-10-17-订单列表2025-10-17 14_01_23.xlsx'

#当前项目的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 是否清理商品名称中的特殊字符
clear_name = False
# 订单文本 规则 ：
# 1.每个订单之间用空行隔开
# 2.每个订单的产品名称、直播价、规格、必须要
# 3.产品名称
# 4.直播价：手动修改为单位
# 5.规格：多个规格用逗号隔开，多个规格会创建多列，生成后手动合并
order_info =[
    {
        '产品名称':'晚安优品冬夏两用防螨垫（绑带款）_150*200*0.5',
        '单位':'个',
        '数量':'1',
        '直播价':'299元/个',
        '规格':'150*200*0.5',
    },
    {
        '产品名称':'晚安优品冬夏两用防螨垫（绑带款）_180*200*0.5',
        '单位':'个',
        '数量':'1',
        '直播价':'299元/个',
        '规格':'180*200*0.5',
    },
    {
        '产品名称':'晚安优品乳胶枕头',
        '单位':'个',
        '数量':'2',
        '直播价':'680元/2个',
        '规格':'56*36*9/11（93±3%纯胶）',
    },
    {
        '产品名称':'晚安优品乳胶床垫1.8米',
        '直播价':'个',
        '数量':'1',
        '单位':'个',
        '规格':'',
    },
    {
        '产品名称':'晚安优品乳胶床垫1.5米',
        '直播价':'个',
        '数量':'1',
        '单位':'个',
        '规格':'',
    }
]
#创建发货表
def create_delivery_table(orders_dict=[]):
    '''
    创建发货表
    参数:
        orders_dict (dict): 订单字典，键为订单号，值为订单详情字典
    返回:
        pd.DataFrame: 按商品名称分类的发货表DataFrame
    '''
    #读取发货表模板
    pf_template= pd.read_excel(os.path.join(current_dir, delivery_template_path))
    #输入直播产品信息
    for  details in orders_dict:
        product_name=details['产品名称']
        pf_template[product_name] = None
           # 规格
        pf_template.loc[0, product_name] = details['规格']
           # 填充单位
        pf_template.loc[1, product_name] = f'单位：{extract_unit(details["单位"])}'

    return pf_template

# 获取文字中的单位
def extract_unit(spec=''):
    # 匹配规格中的单位，找到第一个出现/的地方。获取/之后的第一个字
    # spec_index = spec.find('/')
    # if spec_index != -1:
    #     return spec[spec_index+1:spec_index+2]
    return spec

# 将文本转换为字典的函数
def text_to_order_dict(text):
    # 初始化结果字典
    orders_dict = {}
    
    # 按多个空行分割文本，获取每个订单块
    # 使用正则表达式分割，处理不同数量的换行符
    order_blocks = re.split(r'\n\s*\n+', text.strip())
    
    # 处理每个订单块
    for block in order_blocks:
        if not block.strip():
            continue
            
        # 分割行
        lines = block.strip().split('\n')
        
        # 获取订单号（第一行）
        order_id_line = lines[0].strip()
        # 提取订单号数字部分
        order_id = re.search(r'(\d+)号订单', order_id_line)
        if order_id:
            order_num = order_id.group(1)
        else:
            # 如果无法提取订单号，跳过该块
            continue
            
        # 初始化当前订单的字典
        current_order = {}
        
        # 处理剩余行，提取各个字段
        for line in lines[1:]:
            line = line.strip()
            if not line:
                continue
                
            # 使用正则表达式分割字段名和值
            field_match = re.search(r'(.*?)：(.*)', line)
            if field_match:
                field_name = field_match.group(1).strip()
                field_value = field_match.group(2).strip()
                # 添加到当前订单字典
                current_order[field_name] = field_value
        
        # 添加到结果字典
        orders_dict[order_num] = current_order
    
    return orders_dict

# 到目标表获取发货数量

def get_delivery_quantity(product_name='', id=''):
    """
    获取指定商品和店铺的发货数量

    参数:
        product_name (str): 商品名称，默认为空字符串
        id (str): 店铺Id，默认为空字符串

    返回:
        float/int/None: 匹配商品的发货数量总和，如果没有找到匹配项则返回None
   """
    # 读取订单表Excel文件到DataFrame
    schedule_df = pd.read_excel(order_table_path)
    
    if clear_name:
        # 清理商品名称中的特殊字符和格式问题
        # 移除_x000D_字符（通常是Windows回车符的编码）
        schedule_df['商品名称'] = schedule_df['商品名称'].str.replace('_x000D_', '')
        # 移除换行符
        schedule_df['商品名称'] = schedule_df['商品名称'].str.replace('\n', '')
        # 使用正则表达式将多个连续空格替换
        schedule_df['商品名称'] = schedule_df['商品名称'].str.replace('\s+', '', regex=True)
    
    # 根据商品名称和店铺名称筛选数据行
    product_spec= product_name.split('_')[-1] if '_' in product_name else None
    product_name= product_name.split('_')[0] if '_' in product_name else product_name
    if product_spec:
        product_row = schedule_df[(schedule_df['商品名称'] == product_name) & (schedule_df['店长ID'] == id) & (schedule_df['商品规格'] == product_spec)]
    else:
        product_row = schedule_df[(schedule_df['商品名称'] == product_name) & (schedule_df['店长ID'] == id)]
    
    # 如果找到匹配的数据行
    if not product_row.empty:
        # 计算并返回匹配行的数量总和，跳过NA值
        return product_row['数量'].sum(skipna=True)
    # 如果没有找到匹配的数据行，返回None
    print(f'未找到商品名称为"{product_name},店铺id为：{id},商品规格为：{product_spec}"的发货数量')
    return 0
# 检查数据是否包含非数值
def is_numeric_column(col):
    try:
        pd.to_numeric(col, errors='raise')
        return True
    except:
        return False

def merge_locations_method1(objects):
    """使用字典进行分组合并"""
    
    # 创建字典来分组相同name的对象
    grouped = {}
    
    for obj in objects:
        name = obj['name']
        location = obj['location']
        
        if name not in grouped:
            grouped[name] = {
                'name': name,
                'location': []  # 使用列表存储多个location
            }
        
        # 如果location不在列表中，则添加
        if location not in grouped[name]['location']:
            grouped[name]['location'].append(location)
    
    # 转换为结果列表
    result = list(grouped.values())

    return result
#主程序
if __name__ == '__main__':
   
    # 创建发货表，保留原表样式
    pf_template = create_delivery_table(order_info)

    # 从orders_dict 中获取产品名称为数组
    product_names = [details['产品名称'] for details in order_info]
    # 循环发货表填充发货信息，从第三行到倒数第二行（跳过前2行和最后1行）
    for index, row in pf_template.iloc[2:-1].iterrows():
        for product_name in pf_template.columns[6:]:
            try:
                id = int(row['ID'])
            except:
                # 未查询到id值,跳出内层循环
               print(f'未查询到商品名称为"{product_name}"的店铺id,跳过')
               break
                
            sum = get_delivery_quantity(product_name, id)
            pf_template.at[index, product_name] = sum
    # 统计每一列的总数
    for col in pf_template.columns[6:]:
        # 统计当前列的总和
         # 跳过第一行，因为第一行是规格单位
            total = pf_template[col][2:].sum(skipna=True)
            # 核对该列总数是否正确
            print(f'商品名称为"{product_name}"的发货数量总和为：{total},是否正确，y/n')
            ok=input()
            if ok.lower() == 'y':
                num = next((item['数量'] for item in order_info if item['产品名称'] == product_name), 1)
                pf_template[col][2:].apply(lambda x: x * int(num) if pd.notna(x) else x)
                # 再次求和
                total = pf_template[col][2:].sum(skipna=True)
                pf_template.at[index+1, col] = total
            else:
                print(f'核对数量存在误差，商品名称为"{product_name}"的发货数量总和为：{total}')
                print(f'请输入正确的数量：')
                while True:
                    sure_num = input()
                    if sure_num.isdigit():
                        break
                    else:
                        print('请输入一个整数')
                # 合计需要用sure_num 替代total
                pf_template.at[index+1, col] = total
                pf_template.at[index+2, col] = f'正确：{sure_num}'

    # 保存Excel文件
    # 填充发货信息
    pf_template["运单号"]=None
    pf_template["运费"]=None
    pf_template["物流公司"]=None  
    output_file = os.path.join(current_dir, '发货表统计.xlsx')
    with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
        pf_template.to_excel(writer, index=False)
    wb=load_workbook(output_file)
    ws=wb.active
    # 循环表头。表头使用_分割后取第一个，如果名称相同的分组并合并
    last_col=None
    cell_info=[]
    for cell in ws[1][6:11]:
        if cell.value:
            cell_info.append({
                'name':cell.value.split('_')[0],
                'location':cell.coordinate
            })
    # 名称相同的合并        
    # 找出名称相同的项
    merged = merge_locations_method1(cell_info)
    # 合并相同的名称的单元格
    for item in merged:
        # 把每个item的location 找到最大和最小的 如 A1,A2,A3 则合并A1:A3
        # 找到最大和最小的单元格坐标
        if len(item['location']) > 1:
            max_col = max(loc[:-1] for loc in item['location'])
            min_col = min(loc[:-1] for loc in item['location'])
            # 合并单元格
            ws.merge_cells(f'{min_col}1:{max_col}1')
            ws[min_col+'1']=item['name']
    #保存
    wb.save(output_file)
    print("处理完成。。。。。。")


